#pragma once

#include <QAbstractTableModel>
#include <QAbstractItemDelegate>
#include <QList>

#include "delegate/checkboxdelegate.h"
#include "delegate/comboboxdelegate.h"

enum ColumnType {
    Unknown,
    Text,
    Integer,
    Float,
    Boolean,
    ComboBox,
};

class Filed {
public:
    ColumnType type;

    QString name;
    QString content;
    //combobox
    int index;
    QStringList options;
    //integer
    int ivalue;
    int imin;
    int imax;
    // float
    double fvalue;
    double fmin;
    double fmax;

    // boolean
    bool checked;

    QString note;
};

static QAbstractItemDelegate *comboBoxDelegate(const Filed *filed) {
    if(!filed)
        return nullptr;
    static ComboBoxDelegate *delegate = nullptr;
    if(!delegate)
        delegate = new ComboBoxDelegate(filed->options);
    return delegate;
}

static QAbstractItemDelegate *checkBoxDelegate() {
    if(!filed)
        return nullptr;
    static CheckBoxDelegate *delegate = nullptr;
    if(!delegate)
        delegate = new CheckBoxDelegate;
    return delegate;
}

class TableItem {
public:
    virtual ~TableItem() {
        foreach (Filed *filed, fileds) {
            if(filed) {
                delete filed;
            }
        }
        fileds.clear();
    }

    Filed *filed(int section) {
        if(section < 0 || section >= fileds.size())
            return nullptr;
        return fileds.at(section);
    }

    QVariant value(int section) const {
        Filed *filed = filed(section);
        if(filed) {
            switch (filed->type) {
            case Text:
                return filed->content;
            case Integer:
                return filed->ivalue;
            case Float:
                return filed->fvalue;
            case Boolean:
                return filed->checked;
            case ComboBox:
                return filed->index;
            default:
                break;
            }
        }
        return QVariant();
    }

    bool setValue(int section, const QVariant &value) {
        Filed *filed = filed(section);
        if(filed) {
            switch (filed->type) {
            case Text:
                filed->content = value.toString();
            case Integer:
                filed->ivalue = value.toInt();
            case Float:
                filed->fvalue = value.toDouble();
            case Boolean:
                filed->checked = value.toBool();
            case ComboBox:
                filed->index = value.toInt();
            default:
                return false;
            }
            return true;
        }
        return false;
    }

    QString valueString(int section) const { return value(section).toString(); }

    QString tip(int section) const {
        Filed *filed = filed(section);
        if(filed) {
            if()
        }
        return QString();
    }

    ColumnType  columenType(int section) const {
        Filed *filed = filed(section);
        return filed ? filed->type : Unknown;
    }

    QAbstractItemDelegate *columnDelegate(int section) {
        Filed *filed = filed(section);
        if(filed) {
            switch (filed->type) {
            case Text:
            case Integer:
            case Float:
            case Boolean:
                return checkBoxDelegate();
            case ComboBox:
                return comboBoxDelegate(filed->options);
            default:
                break;
            }
        }
        return nullptr;
    }

    void addFiled(const Filed *filed) {
        fileds.push_back(filed);
    }

protected:
    QList<Filed *> fileds;
};


class TableModel : public QAbstractTableModel
{
    Q_OBJECT
public:
    explicit TableModel(QObject *parent = nullptr);

    int rowCount(const QModelIndex &parent=QModelIndex()) const override;
    int columnCount(const QModelIndex &parent=QModelIndex()) const override;
    QVariant data(const QModelIndex &index, int role) const override;
    bool setData(const QModelIndex &index, const QVariant &value, int role) override;
    Qt::ItemFlags flags(const QModelIndex &index) const override;
    QVariant headerData(int section, Qt::Orientation orientation, int role) const override;

    QStringList headerNames() const;
    void setHeaderNames(const QStringList &headerNames);

    QList<TableItem *> items() const;
    void setItems(const QList<TableItem *> &items);

    QList<Qt::ItemFlags> itemFlags() const;
    void setItemFlags(const QList<Qt::ItemFlags> &itemFlags);

    QList<ColumnType> itemColumnTypes() const;
    void setItemColumnTypes(const QList<ColumnType> &itemColumnTypes);

    void clearItems();
    void addItem(TableItem *item);

protected:
    QStringList m_headerNames;
    QList<TableItem *> m_items;
    QList<Qt::ItemFlags> m_itemFlags;
    QList<ColumnType> m_itemColumnTypes;
};

